package com.mhkj.base.templete.service.impl;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.transaction.Transactional;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.mhkj.base.busiType.entity.BusinessType;
import com.mhkj.base.busiType.service.BusinessTypeService;
import com.mhkj.base.fruitType.entity.FruitType;
import com.mhkj.base.fruitType.service.FruitTypeService;
import com.mhkj.base.templete.entity.PlanTemplete;
import com.mhkj.base.templete.entity.PlanTempleteData;
import com.mhkj.base.templete.repostitory.PlanTempDataRepository;
import com.mhkj.base.templete.service.PlanTempleteDataService;
import com.mhkj.common.enums.NodeProperty;
import com.mhkj.common.enums.PlanTempleteType;
import com.mics.core.common.componet.Pagination;
import com.mics.core.common.exception.ErrorCode;
import com.mics.core.common.exception.ParamException;
import com.mics.core.system.base.service.impl.BaseServiceImpl;
import com.mics.core.system.organizational.bean.Company;
import com.mics.core.system.organizational.bean.Office;
import com.mics.core.system.organizational.bean.Post;
import com.mics.core.system.organizational.service.OrgService;
import com.mics.core.system.rbac.entity.Dictionary;
import com.mics.core.system.rbac.service.DictionaryService;

/**
 * 模板数据
 * @author mics
 * @date 2018年7月20日
 * @version 1.0
 */
@Service
public class PlanTempleteDataServiceImpl extends BaseServiceImpl<PlanTempleteData> implements PlanTempleteDataService{
	@Resource
	private PlanTempDataRepository planTempDataRepository;
	@Resource
	private OrgService orgService;
	@Resource
	private DictionaryService dictionaryService;
	@Resource
	private FruitTypeService fruitTypeService;
	@Resource
	private BusinessTypeService businessTypeService;
	
	@Resource
	public void setPlanTempDataRepository(
			PlanTempDataRepository planTempDataRepository) {
		super.setBaseRepository(planTempDataRepository);
	}
	
	@Override
	@Transactional
	public void handleData(PlanTemplete planTemplete,String[][] result) {
		if(result != null && result.length!=0){
			List<FruitType> fruitTypes = new ArrayList<FruitType>();
			for(int i = 2 ;i < result.length;i++){
				PlanTempleteData planTempleteData = createPlanData(planTemplete,i,result[i],result);
				planTempleteData.setPlanTemplete(planTemplete);
				if(planTempleteData.getNodeProperty() != null){
					if(NodeProperty.N100.getCode().equals(planTempleteData.getNodeProperty().getCode())){ 
						save(planTempleteData);
						FruitType fruitType = new FruitType();
						fruitType.setBusinessType(planTempleteData.getBusinessType());
						fruitType.setName(planTempleteData.getCompleteStandard());
						fruitType.setNodeResult(planTempleteData);
						fruitType.setPlanTemplete(planTempleteData.getPlanTemplete());
						fruitTypeService.save(fruitType);
					}else{
						save(planTempleteData);
						if(fruitTypes.size() > 0){ 
							for(FruitType fruitType : fruitTypes){
								fruitType.setNodePrepare(planTempleteData);
								fruitTypeService.save(fruitType);
							}
						}
						fruitTypes.clear();
					}
				}else{
					FruitType fruitType = fruitTypeService.getByTempleteAndName(planTempleteData.getPlanTemplete(),planTempleteData.getNodeName());
					if(fruitType != null){
						fruitTypes.add(fruitType);
					}
				}
			}
		}else{
			throw new ParamException(ErrorCode.PARAM_ERROR, "不能导入空模板");
		}
	}
	
	/**
	 * 创建模板数据
	 * @author mics
	 * @date 2018年7月20日
	 * @version 1.0
	 * @param planTemplete 
	 * @param i 行
	 * @param data 行数据
	 * @param result 
	 */
	@Transactional
	private PlanTempleteData createPlanData(PlanTemplete planTemplete, int i, String[] data, String[][] result) {
			i=i+1;
			PlanTempleteData planTempleteData = new PlanTempleteData();
			//序号
		    String NO = data[0];
		    planTempleteData.setNO(NO);
			//业务模块
			String busiModeName = data[1];
			if(StringUtils.hasText(busiModeName)){
				BusinessType businessType = businessTypeService.getByName(busiModeName);
				if(businessType != null){
					planTempleteData.setBusinessType(businessType);
				}else{
					throw new ParamException(ErrorCode.EXCEL_READ_ERROR, "在第"+i+"行中，根据业务模块名称"+busiModeName+"，找不到系统存在业务模块");
				}
			}else{
				throw new ParamException(ErrorCode.EXCEL_READ_ERROR, "在第"+i+"行中，业务模块不能为空");
			}
		
			//节点名称
			String nodeName = data[3];
			nodeName = nodeName.trim();
			if(!StringUtils.hasText(nodeName)){
				throw new ParamException(ErrorCode.EXCEL_READ_ERROR, "在第"+i+"行中，节点名称不能为空");
			}
			if(nodeName.length() > 48){
				throw new ParamException(ErrorCode.EXCEL_READ_ERROR, "在第"+i+"行中，节点名称过长");
			}
			int count = planTempDataRepository.findByNameAndPlanTemplete(planTemplete.getId(),nodeName);	
			if(count > 0){
				throw new ParamException(ErrorCode.EXCEL_READ_ERROR, "在第"+i+"行中，'"+nodeName+"'已经存在");
			} 
			planTempleteData.setNodeName(nodeName);
			//完成标准
			String completeStandard = data[4];
			if(StringUtils.hasText(completeStandard)&&completeStandard.length() > 128){
				throw new ParamException(ErrorCode.EXCEL_READ_ERROR, "在第"+i+"行中，完成标准过长");
			}
			planTempleteData.setCompleteStandard(completeStandard);
			//工期
			String datelineStr = data[5];
			if(!StringUtils.hasText(datelineStr) && StringUtils.hasText(data[2])){
				throw new ParamException(ErrorCode.EXCEL_READ_ERROR, "在第"+i+"行中，工期不能为空");
			}
			if(StringUtils.hasText(data[2])){
				try{
					int deadline = Integer.valueOf(datelineStr);
					planTempleteData.setDeadline(deadline);
				}catch(Exception e){
					throw new ParamException(ErrorCode.EXCEL_READ_ERROR,"在第"+i+"行中，标准工期必须是数字");
				}
			}
			
			//工期说明
			String deadlineDesc = data[6];
			if(!planTemplete.getType().getCode().equals(PlanTempleteType.FUNCTION.getCode())){
				if(StringUtils.hasText(data[2])){
					if(!StringUtils.hasText(deadlineDesc)){
						throw new ParamException(ErrorCode.EXCEL_READ_ERROR,"在第"+i+"行中，工期说明不能为空");
					}else{
						if(deadlineDesc.length() > 128){
							throw new ParamException(ErrorCode.EXCEL_READ_ERROR, "在第"+i+"行中，工期说明过长");
						}
						String message = validateDealineDesc(deadlineDesc,result);
						if(message.equals("error")){
							throw new ParamException(ErrorCode.EXCEL_READ_ERROR, "在第"+i+"行中，工期说明格式错误");
						}
					}
				}
			
			}
			planTempleteData.setDeadlineDesc(deadlineDesc);
			//责任单位
			String companyName = data[7];
			if(StringUtils.hasText(companyName)){
				Company company = orgService.getCompanyByName(companyName);
				if(company != null){
					planTempleteData.setCompanyId(company.getId());
				}else{
					throw new ParamException(ErrorCode.PARAM_ERROR,"在第"+i+"行中，根据责任单位"+companyName+",找不到唯一公司");
				}
			}
			//责任部门
			String officeName = data[8];
			if(StringUtils.hasText(officeName)){
				Office office = orgService.getOfficeByCompanyNameAndOfficeName(companyName, officeName);
				if(office !=  null){
					planTempleteData.setOfficeId(office.getId());
				}else{
					throw new ParamException(ErrorCode.PARAM_ERROR,"在第"+i+"行中，根据责任单位"+companyName+",部门名"+officeName+",找不到唯一部门");
				}
			}
			//责任岗位
			String postName = data[9];
			if(StringUtils.hasText(postName)){
				Post post = orgService.getPostByComNameAndOffNameAndPostName(companyName, officeName, postName);
				if(post != null){
					planTempleteData.setPostId(post.getId());
				}else{
					throw new ParamException(ErrorCode.PARAM_ERROR,"在第"+i+"行中，根据责任单位"+companyName+",部门名"+officeName+",岗位名"+postName+",找不到唯一岗位");
				}
			}
			//监督
			String supervise = data[10];
			planTempleteData.setSupervise(supervise);
			//备注
			String remark = data[11];
			planTempleteData.setRemark(remark);
			//节点性质
			String nodePropertyName = data[2];
			if(StringUtils.hasText(nodePropertyName)){
				Dictionary nodeProperty = dictionaryService.getByValue(nodePropertyName.trim());
				if(nodeProperty != null){
					planTempleteData.setNodeProperty(nodeProperty);
				}else{
					throw new ParamException(ErrorCode.PARAM_ERROR,"在第"+i+"行中，根据"+nodePropertyName+"找不到对应节点性质");
				}
			}
			return planTempleteData;
		
	}

	/**
	 * 验证工期说明
	 * @author mics
	 * @date 2018年9月11日
	 * @version 1.0
	 */
	private String validateDealineDesc(String deadlineDesc, String[][] result) {
		if(deadlineDesc.equals("开始")){
			return "ok";
		}
		if(!deadlineDesc.contains("|")){ //验证是否有分隔符
			return "error";
		}
		if("|".equals(deadlineDesc.substring(0, 1)) || "|".equals(deadlineDesc.substring(deadlineDesc.length()-1, deadlineDesc.length()))){
			return "error";
		}
		int count = 0;
		int begin = 0;
		String deadlineDescNew = deadlineDesc;
		while(deadlineDescNew.indexOf("|")!=-1) {
			begin=deadlineDescNew.indexOf("|");
			count++;
			deadlineDescNew = deadlineDescNew.substring(begin+1,deadlineDescNew.length());
	    }
	    if(count != 2){
	    	return "error";
	    }
		String[] array = deadlineDesc.split("\\|");
		//验证工期中节点名称
		String nameGet = array[0].trim();
		int i =0;
		for(String[] data:result){
			if(data[3].equals(nameGet)){
				i++;
			}
		}
		if(i == 0){
			return "error";
		}
		//验证工期中天数
		try{
			Integer.valueOf(array[1]);
		}catch(Exception e){
			return "error";
		}
		//验证条件
		String condition = array[2];
		if(!condition.equals("之内")&&!condition.equals("之后")&&!condition.equals("之前")){
			return "error";
		}
		return "ok";
	}

	@Override
	public Pagination<PlanTempleteData> listByPage(
			PlanTempleteData planTempleteData, int pageIndex, int pageSize) {
		Specification<PlanTempleteData> spec = new Specification<PlanTempleteData> () {  
			/**
			 * 序列号
			 */
			private static final long serialVersionUID = -786003485941679959L;
			@Override
			public Predicate toPredicate(Root<PlanTempleteData> root, CriteriaQuery<?> query,
					CriteriaBuilder criteriaBuilder) {
              List<Predicate> lstPredicates = new ArrayList<Predicate>();
              Join<Object, Object> planTemplete = root.join("planTemplete",JoinType.INNER);
              if(!StringUtils.isEmpty(planTempleteData.getPlanTemplete())){
                  Predicate p1=criteriaBuilder.equal(planTemplete.get("id").as(Long.class), planTempleteData.getPlanTemplete().getId());
                  lstPredicates.add(p1);
              }
              Predicate[] arrayPredicates = new Predicate[lstPredicates.size() ];
              return criteriaBuilder.and(lstPredicates.toArray(arrayPredicates));
	        }
		};
		Page<PlanTempleteData> pageT =  planTempDataRepository.findAll(spec, PageRequest.of(pageIndex, pageSize, Sort.Direction.ASC,"id"));
		Pagination<PlanTempleteData> pagination = new Pagination<PlanTempleteData>();
		pagination.setTotal(planTempDataRepository.count(spec));
		List<PlanTempleteData> planTempleteDatas = pageT.getContent();
		pagination.setData(planTempleteDatas);
		return pagination;
	}

	@Override
	public List<PlanTempleteData> listByTemplete(long templeteId) {
		return planTempDataRepository.listByPlanTempleteId(templeteId);
	}


}
